﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Abreu.Profile.Database;
using System.Collections.ObjectModel;
using Abreu.Profile.Classes;
using Abreu.Profile.ObjectClasses;

namespace CorpAbreu.Common.Models
{
    public class MenuDataSource
    {
        #region Class Members
        private List<Menu> _menuTreeView = new List<Menu>();
        private List<Menu> _menuTreeList = new List<Menu>();
        private List<Menu> _menuAppList = new List<Menu>();
        private List<Menu> _menuAppHeaders = new List<Menu>();

        private Dictionary<String, int> _dicApplicationsParents = new Dictionary<String, int>();
        private Dictionary<int, int> _dicMenuApplications = new Dictionary<int, int>();
        private Collection<int> _listMenuParentsIds = new Collection<int>();
        private CorpAbreuDataContext _corpAbreuDC = new CorpAbreuDataContext();
        #endregion

        /// <summary>
        /// Method to be invoked to build menu
        /// </summary>
        /// <param name="userId"></param>
        /// <returns>List of Menu</returns>
        public List<Menu> GetMenuTree(int? userId)
        {
            UserProfile userInfo = new UserProfile();
            ProfileInfo profileInfo = new ProfileInfo();

            //Get user profile info
            profileInfo = userInfo.GetUserProfile(userId);

            //Build menu
            if(profileInfo != null)
                BuildMenu(profileInfo.ListPermission);

            return _menuTreeView;
        }

        #region Build Menu TreeList
        private void BuildMenu(Collection<PermissionProfile> listPermission)
        {
            for (int i = 0; i < listPermission.Count; i++)
            {
                if (listPermission[i].DenyPermission == null || listPermission[i].DenyPermission == false)
                {
                    //Get Menu Info with P_MenuPermission_sel
                    var objMenuItem = _corpAbreuDC.P_GetMenuPermissionInfo(listPermission[i].MenuId);

                    foreach (P_GetMenuPermissionInfoResult resObjMenuItem in objMenuItem)
                    {
                        //Creates a pair dictionary Menu/Application Id's
                        _dicMenuApplications.Add(resObjMenuItem.MenuId, resObjMenuItem.ApplicationId);

                        if (resObjMenuItem.Level == 0)
                        {
                            Menu menuTree = new Menu();
                            //Build first Node of MenuTree
                            menuTree.Name = resObjMenuItem.Name;
                            menuTree.ID = resObjMenuItem.MenuId;
                            menuTree.AppID = resObjMenuItem.ApplicationId;
                            menuTree.MenuProperty = GetMenuProperties(resObjMenuItem.MenuId);
                            _listMenuParentsIds.Add(resObjMenuItem.MenuId);

                            menuTree.Children = BuildChildNodes(listPermission, resObjMenuItem.MenuId);
                            _menuTreeList.Add(menuTree);
                        }
                    }
                }
            }

            BuildMenuApplications();
            _menuTreeView = BuildHeadersMenu();
        }

        private List<MenuPropertyInfo> GetMenuProperties(int menuId)
        {
            List<MenuPropertyInfo> listPropertiesInfo = new List<MenuPropertyInfo>();

            //Get Menu Properties Info with P_MenuProperties_sel
            var objMenuProperties = _corpAbreuDC.P_GetMenuPropertyInfo(menuId);

            foreach (P_GetMenuPropertyInfoResult resObjMenuPropertiesItem in objMenuProperties)
            {
                MenuPropertyInfo menuPropertyInfo = new MenuPropertyInfo(resObjMenuPropertiesItem.MenuPropertyId,
                                    resObjMenuPropertiesItem.MenuId, resObjMenuPropertiesItem.PropertyId, resObjMenuPropertiesItem.LanguageId,
                                    resObjMenuPropertiesItem.Name, resObjMenuPropertiesItem.Value, resObjMenuPropertiesItem.Notes,
                                    resObjMenuPropertiesItem.BeginDate, resObjMenuPropertiesItem.EndDate, resObjMenuPropertiesItem.StatusMenuProperty);

                listPropertiesInfo.Add(menuPropertyInfo);
            }

            return listPropertiesInfo;
        }

        private List<Menu> BuildChildNodes(Collection<PermissionProfile> listPermission, int menuIdParent)
        {
            List<Menu> menuList = new List<Menu>();

            for (int i = 0; i < listPermission.Count; i++)
            {
                if (listPermission[i].DenyPermission == null || listPermission[i].DenyPermission == false)
                {
                    //Get Menu Info with P_MenuPermission_Sel
                    var objMenuItem = _corpAbreuDC.P_GetMenuPermissionInfo(listPermission[i].MenuId);

                    foreach (P_GetMenuPermissionInfoResult resObjMenuItem in objMenuItem)
                    {
                        if (resObjMenuItem.PrecedentMenuId != null)
                        {
                            if (resObjMenuItem.PrecedentMenuId == menuIdParent)
                            {
                                Menu menuChild = new Menu();

                                //Build Child Node
                                menuChild.Name = resObjMenuItem.Name;
                                menuChild.ID = resObjMenuItem.MenuId;
                                menuChild.MenuProperty = GetMenuProperties(resObjMenuItem.MenuId);

                                //Recursively gets child nodes
                                menuChild.Children = BuildChildNodes(listPermission, resObjMenuItem.MenuId);
                                menuList.Add(menuChild);
                            }
                        }
                    }
                }
            }

            return menuList;
        }
        #endregion

        #region Build Menu
        private List<Menu> BuildHeadersMenu()
        {
            foreach (var pair in _dicApplicationsParents)
            {
                Menu menuItem = new Menu();

                menuItem.Name = pair.Key;
                menuItem.AppID = pair.Value;

                _menuAppHeaders.Add(menuItem);
            }

            _menuAppHeaders = BuildNavigationMenu();

            //Returns menu headers
            return _menuAppHeaders;
        }

        private List<Menu> BuildNavigationMenu()
        {
            List<Menu> menuList = new List<Menu>();

            //In each menu in the menulist create a menulist with her dependencies (app's and menus)
            for (int i = 0; i < _menuAppHeaders.Count; i++)
            {
                Menu menuItem = (Menu)_menuAppHeaders[i];
                //Get the application Id foreach menuItem created
                if (_dicApplicationsParents.Keys.Contains(menuItem.Name.ToString()))
                {
                    int appId = menuItem.AppID;

                    for (int j = 0; j < _menuAppList.Count; j++)
                    {
                        Menu appItem = (Menu)_menuAppList[j];
                        //If is the parent node and is the one already created as tabPage
                        if (appItem.Name.ToString() == menuItem.Name.ToString())
                        {
                            //Foreach relation between menu Id and application Id moves the node of menu tree to the new menu Tab
                            foreach (var pair in _dicMenuApplications)
                            {
                                if (pair.Value == appId)
                                {
                                    for (int k = 0; k < _listMenuParentsIds.Count; k++)
                                    {
                                        for (int l = 0; l < _menuTreeList.Count; l++)
                                        {
                                            Menu menuItemAux = (Menu)_menuTreeList[l];
                                            if (_listMenuParentsIds[k] == (int)menuItemAux.ID)
                                            {
                                                if ((int)menuItemAux.ID == pair.Key)
                                                {
                                                    appItem.Children.Add(menuItemAux);
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            //Obtain the childnode of the parent one and add it to the tab page control that represents the parent application ID
                            menuItem.Children.Add(appItem);
                        }
                    }
                }

                menuList.Add(menuItem);
            }

            //Returns menu List
            return menuList;
        }
        #endregion

        #region BuildApplications Menu List
        private void BuildMenuApplications()
        {
            List<int> listAppId = new List<int>();

            foreach (Menu menu in _menuTreeList)
            {
                if (!listAppId.Contains(menu.AppID))
                {
                    listAppId.Add(menu.AppID);

                    //Get Applications info with P_ApplicationInfo_Sel
                    var objApplicationItem = _corpAbreuDC.P_GetApplicationInfo(menu.AppID);

                    foreach (P_GetApplicationInfoResult resObjApplicationItem in objApplicationItem)
                    {
                        if (resObjApplicationItem.LevelApplication == 0)
                        {
                            Menu menuApp = new Menu();
                            //Build first Node of application menu
                            menuApp.Name = resObjApplicationItem.Name;
                            menuApp.AppID = resObjApplicationItem.ApplicationId;
                            menuApp.ApplicationProperty = GetApplicationProperties(resObjApplicationItem.ApplicationId);
                            _dicApplicationsParents.Add(resObjApplicationItem.Name, resObjApplicationItem.ApplicationId);


                            menuApp.Children = BuildChildApplicationNodes(resObjApplicationItem.ApplicationId);
                            _menuAppList.Add(menuApp);
                        }
                    }
                }
            }
        }

        private List<ApplicationPropertyInfo> GetApplicationProperties(int applicationId)
        {
            List<ApplicationPropertyInfo> listPropertiesInfo = new List<ApplicationPropertyInfo>();

            //Get Application Properties Info with P_ApplicationPropertyInfo_Sel
            var objApplicationProperties = _corpAbreuDC.P_GetApplicationPropertyInfo(applicationId);

            foreach (P_GetApplicationPropertyInfoResult resObjapplicationPropertiesItem in objApplicationProperties)
            {
                ApplicationPropertyInfo applicationPropertyInfo = new ApplicationPropertyInfo(resObjapplicationPropertiesItem.ApplicationPropertyId,
                                    resObjapplicationPropertiesItem.ApplicationId, resObjapplicationPropertiesItem.PropertyId, resObjapplicationPropertiesItem.LanguageId,
                                    resObjapplicationPropertiesItem.Name, resObjapplicationPropertiesItem.Value, resObjapplicationPropertiesItem.Notes,
                                    resObjapplicationPropertiesItem.BeginDate, resObjapplicationPropertiesItem.EndDate, resObjapplicationPropertiesItem.StatusApplicationProperty);

                listPropertiesInfo.Add(applicationPropertyInfo);
            }

            return listPropertiesInfo;
        }

        private List<Menu> BuildChildApplicationNodes(int applicationIdParent)
        {
            List<Menu> menuList = new List<Menu>();

            foreach (Menu menu in _menuTreeList)
            {
                //Get Applications info with P_ApplicationInfo_Sel
                var objApplicationItem = _corpAbreuDC.P_GetApplicationInfo(menu.AppID);

                foreach (P_GetApplicationInfoResult resObjApplicationItem in objApplicationItem)
                {
                    if (resObjApplicationItem.PrecedentAplicationId != null)
                    {
                        if (resObjApplicationItem.PrecedentAplicationId == applicationIdParent)
                        {
                            Menu menuApp = new Menu();

                            //Build Child Node
                            menuApp.Name = resObjApplicationItem.Name;
                            menuApp.AppID = resObjApplicationItem.ApplicationId;
                            menuApp.ApplicationProperty = GetApplicationProperties(resObjApplicationItem.ApplicationId);
                           
                            //Recursively gets child nodes
                            BuildChildApplicationNodes(resObjApplicationItem.ApplicationId);
                            menuList.Add(menuApp);
                        }
                    }
                }
            }
            return menuList;
        }
        #endregion
    }
}
